VPNサービスTailscaleを使ってAWS VPCプライベートサブネット内のリソースと通信してみた
Tailscale はデバイス・アプリケーション同士をP2Pのメッシュネットワークで通信させるVPNサービスです。 Linuxカーネルにも組み込まれているWireGuardをベースに実装されています。
Windows/Linux/スマートフォンなどにクライアントプログラムをインストールすると、ごく僅かな設定だけで利用できます。
AWS VPC展開する場合、、たくさんのインスタンスへのインストールが発生する上、RDSのようなマネージドサービスにはユーザープログラムはインストールできません。
そこで、VPC内にゲートウェイとなるEC2インスタンス(Tailscaleドキュメントで言う所の「サブネットルーター」)を1台だけセットアップし、VPC内の各種リソースと通信する方法を紹介します。
- 左側がTailscaleクライアントをインストールしたTailscaleネットワーク
- 右側がAWS VPC
- 中央にいるのがVPC内に構築したサブネットルーターノード
※図は「Subnet routers and traffic relay nodes · Tailscalehttps://tailscale.com/kb/1019/subnets/」から
Tailscaleネットワーク内のノードからはAWS VPCのプライベートなリソースへの通信、例えば、EC2インスタンスへのSSH、RDSへのデータベース接続などができます。
やってみた
AWS VPC内にサブネットルーターをセットアップし、クライアントからVPCのプライベートサブネットにあるEC2にSSHできることを確認します。
環境
- Tailscale : 1.18.1
- AWS VPC
- EC2 : Amazon Linux 2(x86_64)
Tailscale のアカウント開設
まずは次の URL から Tailscale のアカウントを開設します。
Google/Microsoft/GitHubのアカウントでSSOしてアカウントが必要です。
次に、実行環境向けのTailscaleクライアントをダウンロードします。
管理画面のマシン一覧には、インストールしたデバイスを確認できます。
各デバイスには、キャリアグレードNAT(CGNAT)用に予約されている 100.64.0.0/10 のIPアドレスが割り振られます。
サインアップの詳細は次のドキュメントをご確認ください。
Getting Started with Tailscale · Tailscale
AWS リソースの作成
次にAWSに
- 新規VPC(Tailscale Subnet Router for AWS VPC Demo)
- サブネットルーター用EC2(Tailscale Relay Server)
- 接続確認用EC2(Tailscale Target Server)
を構築します。
次のドキュメントと同じ構成です。
Connect to an AWS VPC using subnet routes · Tailscale
次のGitHubのレポジトリにあるCloudFormationのテンプレートを流すだけです。
ポイントは以下の3点です。
サブネットルーターをNATゲートウェイ配下のプライベートサブネットに配置することも可能ですが、 パフォーマンスの観点から、ドキュメント通り、パブリックサブネットに設置しています。
デバイス同士がP2Pで通信して、レイテンシーを軽減できるよう、サブネットルーターのセキュリティグループのインバウンドルールでは、UDPの41641ポートを許可しています。
サブネットルーター経由でVPC内のリソースにアクセスできるよう、これらリソースのセキュリティグループのインバウンドルールでは サブネットルーターにアタッチしたセキュリティグループをソースとする通信を許可しています。
TailScaleの初期設定
CloudFormationでは、EC2のユーザーデータでサブネットルーターインスタンスへのTailScaleのインストールとIPフォワードの有効化までを行っています。
ルーターインスタンスに接続し、手動でノードをTailscaleネットワークに参加させます。
Systems Manager Session Manager でシェルアクセスします(そのため、公式ドキュメントにあるようなSSH通信は許可していません)。
tailscale がインストールされていることを確認します。
$ tailscale version 1.18.1 tailscale commit: 0a43340482a86c3c227aa133c8f1ee9e36360b4b other commit: b05dc05d46c4a3c7e634ef0695221985be99274d go version: go1.17.2-ts7037d3ea51
次のコマンドで tailscale
を起動します。
$ sudo tailscale up --advertise-routes=10.0.0.0/16 --hostname=vpc-subnet-router To authenticate, visit: https://login.tailscale.com/a/abcde
リレーする CIDR(=AWS VPC)を --advertise-routes
で指定し、--hostname
でこのインスタンスのノード名を指定します。
認証用のRULをクリックし、Tailscale サイトにログインして認証します。
$ tailscale status
コマンドから、EC2インスタンスが Tailscaleネットワークに参加したことがわかります。
$ tailscale status 100.91.173.90 vpc-subnet-router foo@ linux - 100.126.250.25 mac-office foo@ macOS idle, tx 18184 rx 20840
Tailscale 用の NIC(tailscale0
) が追加されています。
$ tailscale ip -4 100.91.173.90 $ ip addr show tailscale0 3: tailscale0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1280 qdisc pfifo_fast state UNKNOWN group default qlen 500 link/none inet 100.91.173.90/32 scope global tailscale0 valid_lft forever preferred_lft forever inet6 fd7a:115c:a1e0:ab12:4843:cd96:625b:ad5a/128 scope global valid_lft forever preferred_lft forever inet6 fe80::df00:75ec:4275:f77c/64 scope link stable-privacy valid_lft forever preferred_lft forever
クライアントからサブネットルーターにアクセス
次に、クライアントからAWS VPCにあるサブネットルーター用EC2インスタンスにSSH接続してみます。
IPアドレスとして、100 で始まる TailscaleネットワークのIPアドレスを指定します。
$ ssh -i /path/to.pem ec2-user@100.91.173.90 ... __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ [ec2-user@ip-10-0-0-18 ~]$
クライアントからVPC 内のリソースにアクセス
ここからが本題です。 サブネットルーターをいかした通信を試します。
サブネットルーター配下にある、TailscaleがインストールされていないAWS VPCのリソースにアクセスします。
準備として、Tailscale管理コンソールで以下の操作を行います。
- アドバタイズするサブネットを承認
- 鍵の有効期限を無効化
アドバタイズするサブネットを承認
サブネットルーター内で tailscale を起動する際、 --advertise-routes=10.0.0.0/16
でアドバタイズするサブネットを指定しました。
追加するノードの承認を管理コンソールで行ったように、このサブネットの承認もコンソールで行います。
マシーン一覧のアクションメニューから Review route settings
を選択し、アドバタイズするサブネットを Enable します。
鍵の有効期限を無効化
同様に、サブネットルーターデバイス(vpc-subnet-router
)を選択し、メニューから Disable key expiry
を指定して、鍵の有効期限を無効化します。
デフォルトでは 180 日ごとにノードの再認証が必要です。
SSH の接続テスト
上記設定を済ませ、VPC プライベートサブネットにある EC2 に対して traceroute してみます。
$ traceroute 10.0.2.146 traceroute to 10.0.2.146 (10.0.2.146), 64 hops max, 52 byte packets 1 100.121.197.86 (100.121.197.86) 26.016 ms 19.954 ms 19.784 ms 2 10.0.2.146 (10.0.2.146) 19.091 ms 19.979 ms 19.222 ms
パケットはサブネットルーター(100.121.197.86/10.0.0.18)を経由して届きます。
SSH 接続を試します。
$ ssh -i /path/to.pem ec2-user@10.0.2.146 __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ [ec2-user@ip-10-0-2-146 ~]$
クライアント(Mac)のルーティングテーブルを確認します。
$ netstat -rn Routing tables Internet: Destination Gateway Flags Netif Expire default link#17 UCSI utun2 10/16 link#17 UCS utun2 100.91.173.90/32 link#17 UCS utun2 100.100.100.100/32 link#17 UCS utun2 100.126.250.25 100.126.250.25 UH utun2 224.0.0/4 link#17 UmCSI utun2 255.255.255.255/32 link#17 UCSI utun2 ...
※ Tailscale 向けのものを抜粋
100.91.173.90 はAWS VPC内のサブネットルーター、100.126.250.25 はクライアント(Mac)のIPアドレスです。
RDS の接続テスト
パブリックIPアドレスを割り振っていない RDS の場合、VPC外でもホスト名はプライベートIPアドレスで名前解決されます。
同様にして、RDSに接続することも可能です。
$ dig +short database-1.xxx.eu-central-1.rds.amazonaws.com 10.0.3.176 $ mysqlsh --uri=admin@database-1.xxx.eu-central-1.rds.amazonaws.com:3306 ... MySQL database-1.xxx.eu-central-1.rds.amazonaws.com:3306 ssl JS >
利用費
小規模な個人用途であれば、Tailscaleは無料、その他のケースでは有料です。
詳細は Pricing ページをご確認ください。
最後に
WireGuardをベースにしたVPNサービスTailscaleを用い、AWS VPC内のリソースにプライベート接続する方法を紹介しました。
Tailscaleを使いこなしたい場合、マニュアルの他、次の技術ブログの一読をおすすめします。
また、WireGuard については、プロトコル考案者によるBlack Hat 2018での発表がおすすめです。
それでは。